/**
 * @Title: ServerMonitorService.java
 * @Package: com.itic.appbase.applications.monitor.service
 * @author: idong
 * @date: May 22, 2015 4:10:33 PM
 * @version: V1.0
 */

package com.itic.appbase.applications.monitor.service;

import com.itic.appbase.applications.monitor.vo.CPUInfo;
import com.itic.appbase.applications.monitor.vo.FileSystemInfo;
import com.itic.appbase.applications.monitor.vo.MemInfo;
import com.itic.appbase.applications.monitor.vo.ServerInfo;
import com.itic.appbase.framework.common.service.BaseService;
import com.itic.appbase.framework.plugins.logger.Log;
import com.itic.appbase.framework.utils.NumericHelper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.FileSystem;
import org.hyperic.sigar.FileSystemUsage;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.springframework.stereotype.Service;

/**
 * <p>
 * Company: itic
 * </p>
 * 
 * @author: idong
 * @date: May 22, 2015 4:10:33 PM
 * @version: V1.0
 */
@Service
public class ServerMonitorService
        extends BaseService {

    /**
     * 获取主机及操作系统相关信息
     * 
     * @return
     */
    public ServerInfo getServerInfo() {
        ServerInfo server = new ServerInfo("Unknown Host", "Unknown IP", "Unknown OS Type", "Unknown OS Version", "--",
                "--");
        // 主机名称,IP
        Sigar sigar = new Sigar();
        try {
            server.setHostName(sigar.getNetInfo().getHostName());
            server.setHostIp(sigar.getNetInterfaceConfig().getAddress());
        } catch (SigarException se) {
            Log.error("读取NET错误,{}", se);
        } finally {
            sigar.close();
        }
        // 操作系统
        OperatingSystem osInfo = OperatingSystem.getInstance();
        server.setOsType(osInfo.getVendorName());
        server.setOsArch(osInfo.getArch());
        server.setOsDes(osInfo.getDescription());
        server.setOsVersion(osInfo.getVendorVersion());
        return server;
    }

    /**
     * 获取文件系统相关信息
     * 
     * @return
     */
    public List<FileSystemInfo> getFileSystemInfo() {
        List<FileSystemInfo> resultList = new ArrayList<FileSystemInfo>();
        Sigar sigar = new Sigar();
        try {
            // 文件系统列表
            FileSystem[] fslist = sigar.getFileSystemList();
            for (FileSystem fs : fslist) {
                FileSystemInfo fsInfo = new FileSystemInfo();
                FileSystemUsage fsu = sigar.getFileSystemUsage(fs.getDirName());
                // 非空文件系统
                if (fsu.getTotal() > 0) {
                    fsInfo.setFsName(fs.getDevName());
                    fsInfo.setFsDir(fs.getDirName());
                    fsInfo.setFsTotal(NumericHelper.parseBitSize(fsu.getTotal() * 1024, 2));
                    fsInfo.setFsUsed(NumericHelper.parseBitSize((fsu.getTotal() - fsu.getFree()) * 1024, 2));
                    fsInfo.setFsFree(Double.parseDouble(presentLongDiv(fsu.getFree(), fsu.getTotal())) * 100 + "%");
                    resultList.add(fsInfo);
                }
            }
        } catch (SigarException se) {
            Log.error("读取文件系统错误,{}", se);
            FileSystemInfo fsInfo = new FileSystemInfo("--");
            resultList.add(fsInfo);
        } finally {
            sigar.close();
        }
        Collections.sort(resultList);
        return resultList;
    }

    /**
     * 获取CPU相关信息
     * 
     * @return
     */
    public CPUInfo getCpuInfo() {
        CPUInfo cpu = new CPUInfo("--");
        Sigar sigar = new Sigar();
        try {
            CpuPerc cpuCerc = sigar.getCpuPerc();
            cpu.setFree(presentDouble(cpuCerc.getIdle()));
            cpu.setNiceUsed(presentDouble(cpuCerc.getNice()));
            cpu.setSysUsed(presentDouble(cpuCerc.getSys()));
            cpu.setTotal(presentDouble(cpuCerc.getCombined()));
            cpu.setUserUsed(presentDouble(cpuCerc.getUser()));
        } catch (SigarException se) {
            Log.error("读取CPU错误,{}", se);
        } finally {
            sigar.close();
        }
        return cpu;
    }

    /**
     * 获取内存相关信息
     * 
     * @return
     */
    public MemInfo getMemInfo() {
        MemInfo memory = new MemInfo("--");
        Sigar sigar = new Sigar();
        try {
            Mem mem = sigar.getMem();
            memory.setFree(NumericHelper.parseBitSize(mem.getActualFree(), 2) + "  :  "
                    + Double.parseDouble(presentLongDiv(mem.getFree(), mem.getTotal())) * 100 + "%");
            memory.setTotal(NumericHelper.parseBitSize(mem.getTotal(), 2) + "  :  100%");
            memory.setUsed(NumericHelper.parseBitSize(mem.getActualUsed(), 2) + "  :  "
                    + Double.parseDouble(presentLongDiv(mem.getUsed(), mem.getTotal())) * 100 + "%");
        } catch (SigarException se) {
            Log.error("读取MEM错误,{}", se);
        } finally {
            sigar.close();
        }
        return memory;
    }

    // 内部工具类
    /**
     * 格式化Double，百分比輸出
     * 
     * @param value
     * @return
     */
    private String presentDouble(double value) {
        return Double.toString(NumericHelper.round(value, 2));
    }

    /**
     * long型除法，格式化並百分比輸出
     * 
     * @param top
     * @param bottom
     * @return
     */
    private String presentLongDiv(long top, long bottom) {
        return presentDouble(NumericHelper.div(NumericHelper.long2Double(top), NumericHelper.long2Double(bottom)));
    }

}
